package com.eugenema.handler;

import com.eugenema.entity.TestStep;
import com.eugenema.util.SeleniumUtil;
import org.openqa.selenium.JavascriptExecutor;
import org.testng.Assert;

/**
 * 检查处理器
 *
 * @author Eugenema
 * @date 2023/3/11 18:51
 **/
public class CheckActionHandler {
    /**
     * 检查 Web 界面元素的文本值
     * <br/>默认取获取到的第一个元素的文本值
     *
     * @param testStep 动作
     * @author Eugenema
     * @date 2023/3/11 18:52
     **/
    public void webCheck(TestStep testStep) throws Exception {
        //获取界面元素文本值
        String actual = SeleniumUtil.getElements(testStep).get(0).getText();
        //TODO 解析 EL 表达式
        String expected = null;
        checkEqualsWeb(actual, expected, testStep.getMessage(), testStep.getId());
    }

    /**
     * 检查 Web 界面元素的属性值
     * <br/>默认取获取到的第一个元素的指定属性值
     *
     * @param testStep 动作
     * @author Eugenema
     * @date 2023/3/11 19:04
     **/
    public void webCheckAttrVal(TestStep testStep) throws Exception {
        //获取界面元素指定属性值
        String actual = SeleniumUtil.getElements(testStep).get(0).getAttribute(testStep.getValue());
        //TODO 解析 EL 表达式
        String expected = null;
        checkEqualsWeb(actual, expected, testStep.getMessage(), testStep.getId());
    }

    /**
     * 检查 Web 界面调用 JS 返回的值
     * <br/>js 举例：
     * <br/>String js = "var user_input = document.getElementById(\"passport_51_user\").title; return user_input;";
     * <br/>如果有 forTimes 参数，则会按照配置进行循环，直至匹配成功或循环结束
     * <br/>如果最终匹配失败，则提示错误信息
     * <br/>若没有 expect 参数，则仅执行 JS
     *
     * @param testStep 动作
     * @author Eugenema
     * @date 2023/3/11 19:10
     **/
    public void webCheckExeJs(TestStep testStep) throws Exception {
        //执行 JS 脚本，并获取返回值
        String actual = (String) ((JavascriptExecutor) SeleniumUtil.getDriver()).executeScript(testStep.getValue());
        if (testStep.getExpect() == null || testStep.getExpect().isEmpty()) {
            return;
        }
        //TODO 解析 EL 表达式
        if (checkEqualsWeb(actual, testStep.getExpect(), testStep.getMessage(), testStep.getId())) {
            // 匹配成功，退出循环
            return;
        }
        if (testStep.getForTimesIntArray() != null) {
            for (int i = 1; i < testStep.getForTimesIntArray()[0]; i++) {
                //执行 JS 脚本，并获取返回值
                actual = (String) ((JavascriptExecutor) SeleniumUtil.getDriver()).executeScript(testStep.getValue());
                //TODO 解析 EL 表达式
                if (checkEqualsWeb(actual, testStep.getExpect(), testStep.getMessage(), testStep.getId())) {
                    // 匹配成功，退出循环
                    return;
                }
                // 匹配失败，继续循环
                Thread.sleep(testStep.getForTimesIntArray()[1] * 1000);
            }
        }
        Assert.fail(String.format("%s：实际值【%s】与预期值【%s】不符", testStep.getMessage(), actual, testStep.getExpect()));
    }

    /**
     * 检查预期与实际是否相等，不等则截图
     *
     * @param actual   实际值
     * @param expected 预期值
     * @param failHint 不符合预期的提示信息
     * @param stepId   对应动作的 id，用作截图名称
     * @author Eugenema
     * @date 2023/3/11 18:56
     **/
    private boolean checkEqualsWeb(String actual, String expected, String failHint, String stepId) {
        try {
            Assert.assertEquals(actual, expected, failHint);
            Thread.sleep(500);
            return true;
        } catch (Error | InterruptedException e) {
            SeleniumUtil.screenShot(stepId);
            return false;
        }
    }
}
